package controllers

import (
	"cvevulner/common"
	"cvevulner/errcode"
	"cvevulner/models"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
)

// Operations about Packages

type CveDetailController struct {
	beego.Controller
}

func (c *CveDetailController) RetData(resp map[string]interface{}) {
	c.Data["json"] = resp
	c.ServeJSON()
}

// @Title Get cvedetail
// @Description get cvedetail
// @Param	cvenumber		type 	string	true
// @Success 200 {object} models.uploadcve
// @Failure 403 :cvenumber is err
// @router / [get]
func (u *CveDetailController) Get() {
	req := u.Ctx.Request
	addr := req.RemoteAddr
	logs.Info("Method: ", req.Method, "The ip address requested by the client: ", addr,
		",Header: ", req.Header, ",body: ", req.Body)
	resp := make(map[string]interface{})
	var cod common.CveOriginDetailData
	resp["errno"] = errcode.RecodeUnknowErr
	resp["errmsg"] = errcode.RecodeText(errcode.RecodeUnknowErr)
	resp["body"] = cod
	//defer u.RetData(resp)
	//Judge whether it is legal
	token := u.GetString("token")
	if token == "" {
		resp["errno"] = errcode.RecodeSessionErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeSessionErr)
		resp["body"] = []ResultData{}
		logs.Error("token acquisition failed")
		u.RetData(resp)
		return
	} else {
		// Check token
		ok := models.CheckToken(token)
		if !ok {
			resp["errno"] = errcode.RecodeSessionErr
			resp["errmsg"] = errcode.RecodeText(errcode.RecodeSessionErr)
			resp["body"] = []ResultData{}
			logs.Error("token verification failed")
			u.RetData(resp)
			return
		}
	}
	cveNum := u.GetString("cveNum")
	if cveNum == "" {
		logs.Error("cveNum, Parameter error")
		resp["errno"] = errcode.RecodeParamErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeParamErr)
		u.RetData(resp)
		return
	}
	cveType, typeError := u.GetInt64("cveType")
	if typeError != nil || cveType == 0 {
		logs.Error("cveType, Parameter error")
		resp["errno"] = errcode.RecodeParamErr
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeParamErr)
		u.RetData(resp)
		return
	}
	// The original data comes from the display of the Chinese Academy of Sciences
	if cveType == 1 {
		var ou models.OriginUpstream
		ouErr := models.GetOriginUpstream(cveNum, &ou)
		if ouErr != nil || ou.CveId == 0 {
			resp["errno"] = errcode.RecodeNodata
			resp["errmsg"] = errcode.RecodeText(errcode.RecodeNodata)
			u.RetData(resp)
			return
		}
		cod.CveNum = ou.CveNum
		cod.CvePackName = ou.PackName
		cod.Title = ou.Title
		cod.CnnvdID = ou.CnnvdID
		cod.CnvdID = ou.CnvdID
		cod.PublishedDate = ou.PublishedDate
		cod.VulStatus = ou.VulStatus
		cod.GetTime = ou.FirstPerTime
		var oud models.OriginUpstreamDesc
		oudErr := models.GetOriginDesc(ou.CveId, &oud)
		if oudErr == nil && oud.DescId > 0 {
			cod.Description.EnDesc = oud.EnDescription
			cod.Description.ZhDesc = oud.ZhDescription
		}
		var ouc models.OriginUpstreamConfig
		oucErr := models.GetOriginConfig(ou.CveId, &ouc)
		if oucErr == nil && ouc.ConfId > 0 {
			var oucn []models.OriginUpstreamConfigNode
			var cf common.CveConfigurations
			oucnNum, oucnErr := models.GetOriginConfigNode(ouc.ConfId, &oucn)
			if oucnNum > 0 && oucnErr == nil {
				for _, nodes := range oucn {
					var cn common.ConfNodes
					cn.Operator = nodes.Operator
					var oucnc []models.OriginUpstreamConfigNodeCpe
					oucncNum, oucncErr := models.GetOriginConfigNodeCpe(nodes.NodeId, &oucnc)
					if oucncNum > 0 && oucncErr == nil {
						for _, cpe := range oucnc {
							var cnc common.NodeCpe
							cnc.Vulnerable = cpe.Vulnerable
							cnc.CpeMatchString = cpe.CpeMatchString
							cnc.Cpe23Uri = cpe.Cpe23Uri
							cn.Cpe = append(cn.Cpe, cnc)
						}
					}
					cf.Nodes = append(cf.Nodes, cn)
				}
			}
			cod.Configurations = cf
		}
		cveImpact, ok := models.QueryCveImpact(ou.CveId)
		if ok && cveImpact.ImpactId > 0 {
			cveScore, ok := models.QueryCveScore(cveImpact.ImpactId, "v3")
			if ok && cveScore.ScoreId > 0 {
				cveScV3, ok := models.QueryCveCvssV3(cveScore.ScoreId)
				if ok && cveScV3.V3Id > 0 {
					logs.Info(cveScV3)
					cod.Impact.BaseMetricV3.CvssV3.Version = cveScV3.Version
					cod.Impact.BaseMetricV3.CvssV3.VectorString = cveScV3.VectorString
					cod.Impact.BaseMetricV3.CvssV3.AttackComplexity = cveScV3.AttackComplexity
					cod.Impact.BaseMetricV3.CvssV3.AttackVector = cveScV3.AttackVector
					cod.Impact.BaseMetricV3.CvssV3.AvailabilityImpact = cveScV3.AvailabilityImpact
					cod.Impact.BaseMetricV3.CvssV3.BaseSeverity = cveScV3.BaseSeverity
					cod.Impact.BaseMetricV3.CvssV3.UserInteraction = cveScV3.UserInteraction
					cod.Impact.BaseMetricV3.CvssV3.BaseScore = cveScV3.BaseScore
					cod.Impact.BaseMetricV3.CvssV3.PrivilegesRequired = cveScV3.PrivilegesRequired
					cod.Impact.BaseMetricV3.CvssV3.ConfidentialityImpact = cveScV3.ConfidentialityImpact
					cod.Impact.BaseMetricV3.CvssV3.IntegrityImpact = cveScV3.IntegrityImpact
					cod.Impact.BaseMetricV3.CvssV3.Scope = cveScV3.Scope
					cod.Impact.BaseMetricV3.ExploitabilityScore = cveScV3.ExploitabilityScore
					cod.Impact.BaseMetricV3.ImpactScore = cveScV3.ImpactScore
				}
			}
			cveScoreV2, ok2 := models.QueryCveScore(cveImpact.ImpactId, "v2")
			if ok2 && cveScoreV2.ScoreId > 0 {
				cveScV2, okV2 := models.QueryCveCvssV2(cveScoreV2.ScoreId)
				if okV2 && cveScV2.V2Id > 0 {
					logs.Info(cveScV2)
					cod.Impact.BaseMetricV2.CvssV2.VectorString = cveScV2.VectorString
					cod.Impact.BaseMetricV2.CvssV2.AccessComplexity = cveScV2.AccessComplexity
					cod.Impact.BaseMetricV2.CvssV2.AvailabilityImpact = cveScV2.AvailabilityImpact
					cod.Impact.BaseMetricV2.CvssV2.Authentication = cveScV2.Authentication
					cod.Impact.BaseMetricV2.CvssV2.Version = cveScV2.Version
					cod.Impact.BaseMetricV2.CvssV2.BaseScore = cveScV2.BaseScore
					cod.Impact.BaseMetricV2.CvssV2.IntegrityImpact = cveScV2.IntegrityImpact
					cod.Impact.BaseMetricV2.CvssV2.ConfidentialityImpact = cveScV2.ConfidentialityImpact
					cod.Impact.BaseMetricV2.CvssV2.AccessVector = cveScV2.AccessVector
					cod.Impact.BaseMetricV2.AcInsufInfo = cveScV2.AcInsufInfo
					cod.Impact.BaseMetricV2.UserInteractionRequired = cveScV2.UserInteractionRequired
					cod.Impact.BaseMetricV2.Severity = cveScV2.Severity
					cod.Impact.BaseMetricV2.ObtainUserPrivilege = cveScV2.ObtainUserPrivilege
					cod.Impact.BaseMetricV2.ObtainAllPrivilege = cveScV2.ObtainAllPrivilege
					cod.Impact.BaseMetricV2.ImpactScore = cveScV2.ImpactScore
					cod.Impact.BaseMetricV2.ExploitabilityScore = cveScV2.ExploitabilityScore
					cod.Impact.BaseMetricV2.ObtainOtherPrivilege = cveScV2.ObtainOtherPrivilege
				}
			}
		}
		var oup models.OriginUpstreamPoc
		oupErr := models.GetOriginPoc(ou.CveId, &oup)
		if oupErr == nil && oup.PocId > 0 {
			cod.Poc.Url = oup.Url
			cod.Poc.Date = oup.Date
			cod.Poc.Source = oup.Source
			cod.Poc.Path = oup.Path
			cod.Poc.Desc = oup.Desc
			cod.Poc.Dbindex = oup.Dbindex
		}
		var oue models.OriginUpstreamEvent
		oueErr := models.GetOriginEvent(ou.CveId, &oue)
		if oueErr == nil && oue.EventId > 0 {
			cod.Event.Date = oue.Date
			cod.Event.Url = oue.Url
			cod.Event.Description = oue.Description
			cod.Event.Title = oue.Title
		}
		var our []models.OriginUpstreamReference
		ourNum, ourErr := models.GetOriginReference(ou.CveId, &our)
		if ourErr == nil && ourNum > 0 {
			for _, reference := range our {
				var crd common.CveReferenceData
				crd.Url = reference.Url
				crd.Name = reference.Name
				crd.Tags = append(crd.Tags, reference.Tags)
				crd.Refsource = reference.Refsource
				cod.ReferenceData = append(cod.ReferenceData, crd)
			}
		}
		var ouv models.OriginUpstreamVulType
		ouvErr := models.GetOriginVulType(ou.CveId, &ouv)
		if ouvErr == nil && ouv.VulId > 0 {
			cod.VulType.Cwe = ouv.Cwe
			cod.VulType.En = ouv.EnDesc
			cod.VulType.Zh = ouv.ZhDesc
		}
		var ouf models.OriginUpstreamFixSuggest
		oufErr := models.GetOriginFixSuggest(ou.CveId, &ouf)
		if oufErr == nil && ouf.FixId > 0 {
			var oufr []models.OriginUpstreamFixSuggestRef
			oufrNum, oufErr := models.GetOriginFixSuggestRef(ouf.FixId, &oufr)
			if oufErr == nil && oufrNum > 0 {
				for _, ref := range oufr {
					var fr common.FixReferences
					fr.Refsource = ref.Refsource
					fr.Name = ref.Name
					fr.Url = ref.Url
					var oufrt []models.OriginUpstreamFixSuggestRefTag
					oufrtNum, oufrtErr := models.GetOriginFixSuggestRefTag(ref.FixRefId, &oufrt)
					if oufrtErr == nil && oufrtNum > 0 {
						for _, tag := range oufrt {
							fr.Tags = append(fr.Tags, tag.Name)
						}
					}
					cod.FixSuggest.References = append(cod.FixSuggest.References, fr)
				}
			}
			cod.FixSuggest.Detail = ouf.Detail
		}
		resp["errno"] = errcode.RecodeOk
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeOk)
		resp["body"] = cod
		u.RetData(resp)
		return
	} else {
		resp["errno"] = errcode.RecodeNodata
		resp["errmsg"] = errcode.RecodeText(errcode.RecodeNodata)
		u.RetData(resp)
		return
	}
}
